package com.zch.starter.metrics.prometheus.springboot.starter.metrics;

import com.alibaba.fastjson.JSON;
import com.zch.starter.metrics.prometheus.springboot.starter.metrics.gauge.AbstractRegisterGauge;
import com.zch.starter.metrics.prometheus.springboot.starter.metrics.gauge.GaugeMetricsInfo;
import com.zch.starter.metrics.prometheus.springboot.starter.utils.TagsUtils;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * export 指标服务 不直接让spring 托管 而是交给MetricsAutoConfiguration 动态配置
 */
@Slf4j
public class ExportMetricsService {
    private MeterRegistry registry;

    public void setRegistry(MeterRegistry registry) {
        this.registry = registry;
    }

    /**
     * 暴漏指标
     * 异常吃掉 不影响主链路
     * @param abstractMetricsInfo
     */
    public void export(AbstractMetricsInfo abstractMetricsInfo) {
        try{
            log.info("reportMetrics metricsName={},metricsInfo={}", abstractMetricsInfo.getMetricsName(),
                    JSON.toJSONString(abstractMetricsInfo));
            if(abstractMetricsInfo ==null||StringUtils.isBlank(abstractMetricsInfo.getType())){
                log.warn("reportMetrics 参数缺失 metricsInfo={} param invalid", abstractMetricsInfo);
                return;
            }
            if(abstractMetricsInfo instanceof GaugeMetricsInfo){
                if(abstractMetricsInfo.GAUGE.equals(abstractMetricsInfo.getType())){
                    GaugeMetricsInfo gaugeMetricsInfo = (GaugeMetricsInfo) abstractMetricsInfo;
                    Gauge.builder(gaugeMetricsInfo.getMetricsName(),gaugeMetricsInfo.getGauge(),
                                    AbstractRegisterGauge::execute)
                            .tags(TagsUtils.getTags(gaugeMetricsInfo.getGauge().getCommonTagMap()))
                            .tags(TagsUtils.getTags(gaugeMetricsInfo.getTagMap()))
                            .register(registry);
                    return;
                }
            }

            if(StringUtils.isBlank(abstractMetricsInfo.getMetricsStatus())){
                log.warn("reportMetrics 参数缺失 metricsInfo={} param invalid", abstractMetricsInfo);
                return;
            }
            if(abstractMetricsInfo.COUNTER.equals(abstractMetricsInfo.getType())){
                Counter counter = Counter.builder(getCounterMetricsName(abstractMetricsInfo.getMetricsName())).description(abstractMetricsInfo.getDescription())
                        .tags(TagsUtils.getTags(abstractMetricsInfo.getTagMap())).register(registry);
                counter.increment();
                return;
            }
            if(abstractMetricsInfo.TIMER.equals(abstractMetricsInfo.getType())){
                Timer timer =
                        Timer.builder(getTimerMetricsName(abstractMetricsInfo.getMetricsName()))
                                .tags(TagsUtils.getTags(abstractMetricsInfo.getTagMap()))
                                .publishPercentiles(0.90,0.95,0.99)
                                .publishPercentileHistogram()
                                .register(registry);
                timer.record(abstractMetricsInfo.getCostTimeMs(), TimeUnit.MILLISECONDS);
                return;
            }

            if(abstractMetricsInfo.COUNT_AND_TIME.equals(abstractMetricsInfo.getType())){
                Counter counter = Counter.builder(getCounterMetricsName(abstractMetricsInfo.getMetricsName())).description(abstractMetricsInfo.getDescription())
                        .tags(TagsUtils.getTags(abstractMetricsInfo.getTagMap())).register(registry);
                counter.increment();
                Timer timer =
                        Timer.builder(getTimerMetricsName(abstractMetricsInfo.getMetricsName()))
                                .tags(TagsUtils.getTags(abstractMetricsInfo.getTagMap()))
                                .publishPercentiles(0.90,0.95,0.99)
                                .publishPercentileHistogram()
                                .register(registry);
                timer.record(abstractMetricsInfo.getCostTimeMs(), TimeUnit.MILLISECONDS);
            }
        }catch (Throwable e){
            log.error("reportMetrics 异常 metricsInfo={} error={}", abstractMetricsInfo,e);

        }
    }

    private static String getCounterMetricsName(String metricsName) {
        if(!metricsName.endsWith("_total")){
            return metricsName + "_total";
        }
        return metricsName;
    }
    private static String getTimerMetricsName(String metricsName) {
        return metricsName;
    }

}
